package com.csw.android.player.exoplayer

import com.csw.android.dev_utils.handler.MainHandler
import com.csw.android.dev_utils.utils.LogUtils
import com.csw.android.player.base.PlayList
import com.csw.android.player.base.PlayerInfo
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.video.VideoSize

/**
 * Exo播放器事件监听，将获取到的状态信息更新到[playerInfo],监听播放状态变化，播放结束时自动播放下一个
 *
 * @param playerInfo 播放器状态信息
 * @param playList 播放列表
 */
class ExoplayerListener(
    val playerInfo: PlayerInfo,
    val playList: PlayList,
) {
    /** 主线程处理器 */
    private val mainHandler = MainHandler()
    /** 进度同步器，播放器播放中则定时每隔一秒刷新一次当前进度 */
    private val progressSynchronizer = object : Runnable {
        override fun run() {
            playerInfo.playProgress = player?.contentPosition ?: 0L
            playerInfo.bufferProgress = player?.contentBufferedPosition ?: 0L
            val sleepTime = 1000 - playerInfo.playProgress % 1000
            if (player?.isPlaying == true) {
                mainHandler.postDelayed(this, sleepTime)
            }
        }
    }
    private val listener = object : Player.Listener {

        /** 播放与暂停状态更新 */
        override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
            super.onPlayWhenReadyChanged(playWhenReady, reason)
            syncButtonPlaying()
        }

        /** 播放状态更新 */
        override fun onPlaybackStateChanged(state: Int) {
            super.onPlaybackStateChanged(state)
            playerInfo.playState = state
            syncButtonPlaying()
            when (state) {
                Player.STATE_IDLE -> {

                }
                Player.STATE_BUFFERING -> {

                }
                Player.STATE_READY -> {
                    playerInfo.duration = player?.duration ?: 0L
                    playerInfo.playProgress = player?.contentPosition ?: 0L
                    playerInfo.bufferProgress = player?.contentBufferedPosition ?: 0L
                }
                Player.STATE_ENDED -> {
                    playList.autoPlayNext()
                }
            }
        }

        /** 切换播放位置 */
        override fun onPositionDiscontinuity(
            oldPosition: Player.PositionInfo,
            newPosition: Player.PositionInfo,
            reason: Int
        ) {
            super.onPositionDiscontinuity(oldPosition, newPosition, reason)
            playerInfo.playProgress = player?.contentPosition ?: 0L
            playerInfo.bufferProgress = player?.contentBufferedPosition ?: 0L
        }

        /** 正在播放状态切换 */
        override fun onIsPlayingChanged(isPlaying: Boolean) {
            super.onIsPlayingChanged(isPlaying)
            mainHandler.removeCallbacks(progressSynchronizer)
            if (isPlaying) {
                mainHandler.post(progressSynchronizer)
            }
        }

        /** 视频尺寸改变 */
        override fun onVideoSizeChanged(videoSize: VideoSize) {
            super.onVideoSizeChanged(videoSize)
            LogUtils.i(this, "onVideoSizeChanged:${videoSize.width},${videoSize.height}")
            playerInfo.videoWidth = videoSize.width
            playerInfo.videoHeight = videoSize.height
            playerInfo.onInfoUpdate.value = System.currentTimeMillis()
        }

        /** 首帧渲染 */
        override fun onRenderedFirstFrame() {
            super.onRenderedFirstFrame()
            LogUtils.i(this, "onRenderedFirstFrame")
        }

        /** 播放错误 */
        override fun onPlayerError(error: PlaybackException) {
            super.onPlayerError(error)
            playList.autoPlayNext()
        }
    }

    /**
     * 同步播放按钮状态，即使资源处于缓冲中，只要缓冲准备完成会直接播放，也视为播放中
     */
    private fun syncButtonPlaying() {
        val p = player
        playerInfo.buttonPlaying = if (p == null) {
            false
        } else {
            p.playWhenReady && (p.playbackState == Player.STATE_BUFFERING || p.playbackState == Player.STATE_READY)
        }
    }

    /**
     * 要监听的播放器
     */
    var player: Player? = null
        set(value) {
            if (field == value) {
                return
            }
            field?.removeListener(listener)
            field = value
            field?.addListener(listener)
        }
}